home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
demo
/
medit.zip
/
MAGMAED.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-08
|
23KB
|
921 lines
#include "stdafx.h" // must be in mfc\src\stdafx.h
#include "magmaed.hpp"
////////////////////////////////////////////////////////////////////
// CMagmaEdit
//
// This code was taken from the CEdit section of mfc\src\winctrl.cpp
//
////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(CMagmaEdit, CEdit)
WNDPROC* CMagmaEdit::GetSuperWndProcAddr()
{
static WNDPROC NEAR pfnSuper;
return &pfnSuper;
}
BOOL CMagmaEdit::Create(DWORD dwStyle, const RECT& rect,
CWnd* pParentWnd, UINT nID)
{
return CWnd::Create("MagmaEdit", NULL, dwStyle, rect, pParentWnd, nID);
}
CMagmaEdit::~CMagmaEdit()
{
DestroyWindow();
}
int CMagmaEdit::GetLastSearchPattern(LPSTR lpBuf)
{
return (int) ::SendMessage(m_hWnd, ME_QUERYSEARCHSTRING, 0, (LONG) lpBuf);
}
/////////////////////////////////////////////////////////////////////////////
// CMagmaEditView
IMPLEMENT_DYNCREATE(CMagmaEditView, CView)
#define new DEBUG_NEW
BEGIN_MESSAGE_MAP(CMagmaEditView, CView)
//{{AFX_MSG_MAP(CMagmaEditView)
ON_WM_CREATE()
ON_WM_PAINT()
ON_MESSAGE(WM_SETFONT, OnSetFont)
ON_EN_CHANGE(AFX_IDW_PANE_FIRST, OnEditChange)
ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateNeedSel)
ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateNeedClip)
ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_ALL, OnUpdateNeedText)
ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
ON_COMMAND(ID_EDIT_CUT, OnEditCut)
ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)
ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll)
ON_UPDATE_COMMAND_UI(ID_EDIT_FIND, OnUpdateNeedText)
ON_UPDATE_COMMAND_UI(ID_EDIT_REPLACE, OnUpdateNeedText)
ON_COMMAND(ID_EDIT_FIND, OnEditFind)
ON_COMMAND(ID_EDIT_REPLACE, OnEditReplace)
ON_UPDATE_COMMAND_UI(ID_EDIT_REPEAT, OnUpdateNeedFind)
ON_COMMAND(ID_EDIT_REPEAT, OnEditRepeat)
ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateNeedSel)
ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR, OnUpdateNeedSel)
ON_COMMAND(ID_EDIT_MARKLINE, OnEditMarkLine)
ON_COMMAND(ID_EDIT_MARKLINERANGE, OnEditMarkLineRange)
ON_COMMAND(ID_EDIT_STREAMMARK, OnEditMarkStream)
ON_COMMAND(ID_EDIT_RECTMARK, OnEditMarkRect)
ON_COMMAND(ID_EDIT_RESETMARK, OnEditMarkReset)
//}}AFX_MSG_MAP
// Standard Print commands (print only - not preview)
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
END_MESSAGE_MAP()
const DWORD CMagmaEditView::dwStyleDefault =
AFX_WS_DEFAULT_VIEW |
WS_HSCROLL | WS_VSCROLL |
ES_AUTOHSCROLL | ES_AUTOVSCROLL |
ES_MULTILINE | ES_NOHIDESEL;
// Operating system specific maximum buffer limit
const DWORD CMagmaEditView::nMaxSize = 0x7FFFFFFFL;
// class name for control creation
static char BASED_CODE szClassName[] = "MagmaEdit";
#ifdef USE_VBX
static HMODULE hMagmaEditModule = NULL;
#else
static HMODULE hMagmaEditModule = ::LoadLibrary("magmaed.dll");
#endif
static HMODULE hBWCCModule = ::LoadLibrary("bwcc.dll");
/////////////////////////////////////////////////////////////////////////////
// CMagmaEditView construction/destruction
CMagmaEditView::CMagmaEditView()
{
#ifdef USE_VBX
if (hMagmaEditModule == NULL)
{
hMagmaEditModule = AfxGetApp()->LoadVBXFile("magmaed.vbx");
ASSERT(hMagmaEditModule > (HMODULE) 32);
AfxGetApp()->UnloadVBXFile("magmaed.vbx");
}
#endif
ASSERT(hMagmaEditModule > (HMODULE) 32);
ASSERT(hBWCCModule > (HMODULE) 32);
m_nTabStops = 8*4; // default 8 character positions
m_hPrinterFont = NULL;
m_hMirrorFont = NULL;
}
CMagmaEditView::~CMagmaEditView()
{
ASSERT(m_hWnd == NULL);
ASSERT(hMagmaEditModule > (HMODULE) 32);
//::FreeLibrary(hMagmaEditModule);
}
WNDPROC* CMagmaEditView::GetSuperWndProcAddr()
{
static WNDPROC NEAR pfnSuper;
return &pfnSuper;
}
//
// How does a CMagmaEdit window get associated with CMagmaEditView?
//
// When the CMagmaEditView is created, it calls CWnd::CreateWindowEx
// in order to create the child inside the view. CreateWindowEx creates
// a CREATESTRUCT data structure with lpszClass set to NULL. It then
// calls CMagmaEditView::PreCreateWindow. In PreCreateWindow, we set the
// cs.lpszClass to "MagmaEdit", the class name of the child window we want
// to create. CreateWindowEx then proceed to create the CMagmaEdit window.
//
BOOL CMagmaEditView::PreCreateWindow(CREATESTRUCT& cs)
{
ASSERT(cs.lpszClass == NULL);
cs.lpszClass = szClassName;
// map default CView style to default CMagmaEditView style
if (cs.style == AFX_WS_DEFAULT_VIEW)
cs.style = dwStyleDefault;
return TRUE;
}
int CMagmaEditView::OnCreate(LPCREATESTRUCT lpcs)
{
if (CView::OnCreate(lpcs) != 0)
return -1;
//
// MODIFICATION : We should change LimitText so it takes a DWORD
//
GetEditCtrl().LimitText((UINT) nMaxSize);
GetEditCtrl().SetTabStops(m_nTabStops);
HFONT hFont = (HFONT) ::SendMessage(GetEditCtrl().m_hWnd, WM_GETFONT, 0, 0L);
LOGFONT lf;
::GetObject(hFont, sizeof(lf), &lf);
m_font.CreateFontIndirect(&lf);
SetFont(&m_font);
return 0;
}
// EDIT controls always turn off WS_BORDER and draw it themselves
#define CX_BORDER 1
#define CY_BORDER 1
void CMagmaEditView::CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType)
{
if (nAdjustType != 0)
{
// default behavior for in-place editing handles scrollbars
DWORD dwStyle = GetStyle();
if (dwStyle & WS_VSCROLL)
lpClientRect->right += ::GetSystemMetrics(SM_CXVSCROLL) - CX_BORDER;
if (dwStyle & WS_HSCROLL)
lpClientRect->bottom += ::GetSystemMetrics(SM_CYHSCROLL) - CY_BORDER;
return;
}
::AdjustWindowRect(lpClientRect, GetStyle() | WS_BORDER, FALSE);
}
/////////////////////////////////////////////////////////////////////////////
// CMagmaEditView document like functions
void CMagmaEditView::DeleteContents()
{
ASSERT_VALID(this);
ASSERT(m_hWnd != NULL);
SetWindowText(NULL);
ASSERT_VALID(this);
}
void CMagmaEditView::Serialize(CArchive& ar)
// Read and write CMagmaEditView object to archive, with length prefix.
{
ASSERT_VALID(this);
ASSERT(m_hWnd != NULL);
if (ar.IsStoring())
{
DWORD nLen = GetBufferLength();
ar << nLen;
WriteToArchive(ar);
}
else
{
DWORD dwLen;
ar >> dwLen;
if (dwLen > nMaxSize)
{
AfxThrowArchiveException(CArchiveException::badIndex);
ASSERT(FALSE);
}
ReadFromArchive(ar, dwLen);
}
ASSERT_VALID(this);
}
void CMagmaEditView::ReadFromArchive(CArchive& ar, DWORD nLen)
// Read certain amount of text from the file, assume at least nLen
// bytes are in the file.
{
(void) nLen;
ASSERT_VALID(this);
::SendMessage(GetEditCtrl().m_hWnd, ME_OPENFILE, ar.GetFile()->m_hFile, 0L);
Invalidate();
ASSERT_VALID(this);
}
void CMagmaEditView::WriteToArchive(CArchive& ar)
// Write just the text to an archive, no length prefix.
{
ASSERT_VALID(this);
TRY
{
::SendMessage(GetEditCtrl().m_hWnd, ME_WRITEFILE, ar.GetFile()->m_hFile, 0L);
}
CATCH_ALL(e)
{
THROW_LAST();
ASSERT(FALSE);
}
END_CATCH_ALL
ASSERT_VALID(this);
}
void CMagmaEditView::SerializeRaw(CArchive& ar)
// Read/Write object as stand-alone file.
{
ASSERT_VALID(this);
if (ar.IsStoring())
{
WriteToArchive(ar);
}
else // reading from a file
{
CFile* pFile = ar.GetFile();
ASSERT(pFile->GetPosition() == 0);
DWORD nFileSize = pFile->GetLength();
// Make sure that the file isn't larger than what the buffer can hold
if (nFileSize > nMaxSize)
{
AfxMessageBox(AFX_IDP_FILE_TOO_LARGE);
AfxThrowUserException();
ASSERT(FALSE);
}
ReadFromArchive(ar, nFileSize);
}
ASSERT_VALID(this);
}
/////////////////////////////////////////////////////////////////////////////
// CMagmaEditView drawing
void CMagmaEditView::OnPaint()
{
// do not call CView::OnPaint since it will call OnDraw
CWnd::OnPaint();
}
void CMagmaEditView::OnDraw(CDC*)
{
// do nothing here since CWnd::OnPaint() will repaint the EDIT control
}
/////////////////////////////////////////////////////////////////////////////
// CMagmaEditView commands
void CMagmaEditView::OnUpdateNeedSel(CCmdUI* pCmdUI)
{
//
// Checks to see if there is any selected text in the buffer
//
// MODIFICATION : Add check for line marks
//
ASSERT_VALID(this);
#if 0
//
// Ifdef'ed out.. we should always be able to cut
//
int nStartChar, nEndChar;
GetEditCtrl().GetSel(nStartChar, nEndChar);
pCmdUI->Enable(nStartChar != nEndChar);
#else
pCmdUI->Enable(TRUE);
#endif
ASSERT_VALID(this);
}
void CMagmaEditView::OnUpdateNeedClip(CCmdUI* pCmdUI)
{
//
// Checks to see if there is text waiting in the clipboard. If so,
// the Paste menu item is enabled.
//
ASSERT_VALID(this);
pCmdUI->Enable(::IsClipboardFormatAvailable(CF_TEXT));
ASSERT_VALID(this);
}
void CMagmaEditView::OnUpdateNeedText(CCmdUI* pCmdUI)
{
ASSERT_VALID(this);
pCmdUI->Enable(GetBufferLength() != 0);
ASSERT_VALID(this);
}
void CMagmaEditView::OnUpdateEditUndo(CCmdUI* pCmdUI)
{
ASSERT_VALID(this);
//
// Checks to see if anything is in the UNDO stack
//
pCmdUI->Enable(GetEditCtrl().CanUndo());
ASSERT_VALID(this);
}
void CMagmaEditView::OnEditChange()
{
ASSERT_VALID(this);
GetDocument()->SetModifiedFlag();
ASSERT_VALID(this);
}
void CMagmaEditView::OnEditCut()
{
ASSERT_VALID(this);
GetEditCtrl().Cut();
ASSERT_VALID(this);
}
void CMagmaEditView::OnEditCopy()
{
ASSERT_VALID(this);
GetEditCtrl().Copy();
ASSERT_VALID(this);
}
void CMagmaEditView::OnEditPaste()
{
ASSERT_VALID(this);
GetEditCtrl().Paste();
ASSERT_VALID(this);
}
void CMagmaEditView::OnEditClear()
{
ASSERT_VALID(this);
GetEditCtrl().Clear();
ASSERT_VALID(this);
}
void CMagmaEditView::OnEditUndo()
{
ASSERT_VALID(this);
GetEditCtrl().Undo();
ASSERT_VALID(this);
}
void CMagmaEditView::OnEditSelectAll()
{
ASSERT_VALID(this);
//
// Select everything in the buffer
//
GetEditCtrl().SetSel(0, -1);
ASSERT_VALID(this);
}
void CMagmaEditView::OnEditMarkLine()
{
ASSERT_VALID(this);
::SendMessage(GetEditCtrl().m_hWnd, ME_MARKLINE, 0, 0L);
ASSERT_VALID(this);
}
void CMagmaEditView::OnEditMarkLineRange()
{
ASSERT_VALID(this);
::SendMessage(GetEditCtrl().m_hWnd, ME_MARKLINERANGE, 0, 0L);
ASSERT_VALID(this);
}
void CMagmaEditView::OnEditMarkStream()
{
ASSERT_VALID(this);
::SendMessage(GetEditCtrl().m_hWnd, ME_STREAMMARK, 0, 0L);
ASSERT_VALID(this);
}
void CMagmaEditView::OnEditMarkRect()
{
ASSERT_VALID(this);
::SendMessage(GetEditCtrl().m_hWnd, ME_RECTMARK, 0, 0L);
ASSERT_VALID(this);
}
void CMagmaEditView::OnEditMarkReset()
{
ASSERT_VALID(this);
::SendMessage(GetEditCtrl().m_hWnd, ME_RESETMARK, 0, 0L);
ASSERT_VALID(this);
}
/////////////////////////////////////////////////////////////////////////////
// CMagmaEditView Font Handling
LRESULT CMagmaEditView::OnSetFont(WPARAM wParam, LPARAM lParam)
{
ASSERT_VALID(this);
Default();
GetEditCtrl().SetTabStops(m_nTabStops);
ASSERT_VALID(this);
return 0;
}
void CMagmaEditView::SetPrinterFont(CFont* pFont)
{
ASSERT_VALID(this);
m_hPrinterFont = (HFONT)pFont->GetSafeHandle();
ASSERT_VALID(this);
}
CFont* CMagmaEditView::GetPrinterFont() const
{
ASSERT_VALID(this);
return CFont::FromHandle(m_hPrinterFont);
}
/////////////////////////////////////////////////////////////////////////////
// CMagmaEditView attributes
DWORD CMagmaEditView::GetBufferLength() const
{
ASSERT_VALID(this);
ASSERT(m_hWnd != NULL);
DWORD nLen = GetWindowTextLength();
return nLen;
}
/////////////////////////////////////////////////////////////////////////////
// CMagmaEditView Find & Replace
void CMagmaEditView::OnUpdateNeedFind(CCmdUI* pCmdUI)
{
ASSERT_VALID(this);
//
// Checks to see if there is a previous search pattern
//
// MODIFICATION : Use a MagmaEdit message to query the previous
// search string
// GetEditCtrl().GetLastSearchPattern() > 0
//
//
pCmdUI->Enable(GetBufferLength() != 0 &&
GetEditCtrl().GetLastSearchPattern() > 0);
ASSERT_VALID(this);
}
void CMagmaEditView::OnEditFind()
{
ASSERT_VALID(this);
OnEditFindReplace(TRUE);
ASSERT_VALID(this);
}
void CMagmaEditView::OnEditReplace()
{
ASSERT_VALID(this);
OnEditFindReplace(FALSE);
ASSERT_VALID(this);
}
void CMagmaEditView::OnEditRepeat()
{
ASSERT_VALID(this);
if (::SendMessage(GetEditCtrl().m_hWnd, ME_SEARCHAGAIN, 0, 0L) == 0)
OnTextNotFound();
}
void CMagmaEditView::OnEditFindReplace(BOOL bFindOnly)
{
ASSERT_VALID(this);
if (::SendMessage(GetEditCtrl().m_hWnd,
(bFindOnly) ? ME_FSEARCH : ME_FREPLACE,
0,
0L) == 0)
OnTextNotFound();
}
void CMagmaEditView::OnFindNext(LPCSTR lpszFind, BOOL bNext, BOOL bCase)
{
ASSERT_VALID(this);
}
void CMagmaEditView::OnReplaceSel(LPCSTR lpszFind, BOOL bNext, BOOL bCase,
LPCSTR lpszReplace)
{
ASSERT_VALID(this);
}
void CMagmaEditView::OnReplaceAll(LPCSTR lpszFind, LPCSTR lpszReplace,
BOOL bCase)
{
ASSERT_VALID(this);
}
LRESULT CMagmaEditView::OnFindReplaceCmd(WPARAM, LPARAM lParam)
{
ASSERT_VALID(this);
return 0;
}
void CMagmaEditView::OnTextNotFound(LPCSTR)
{
ASSERT_VALID(this);
MessageBeep(0);
}
/////////////////////////////////////////////////////////////////////////////
// CMagmaEditView Tab Stops
void CMagmaEditView::SetTabStops(int nTabStops)
{
ASSERT_VALID(this);
m_nTabStops = nTabStops;
GetEditCtrl().SetTabStops(m_nTabStops);
Invalidate();
ASSERT_VALID(this);
}
/////////////////////////////////////////////////////////////////////////////
// CMagmaEditView diagnostics
#ifdef _DEBUG
void CMagmaEditView::AssertValid() const
{
CView::AssertValid();
ASSERT_VALID(&m_aPageStart);
if (m_hPrinterFont != NULL)
ASSERT_VALID(CFont::FromHandle(m_hPrinterFont));
if (m_hMirrorFont != NULL)
ASSERT_VALID(CFont::FromHandle(m_hMirrorFont));
}
void CMagmaEditView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
AFX_DUMP1(dc, "\nm_nTabStops = ", m_nTabStops);
if (m_hPrinterFont != NULL)
AFX_DUMP1(dc, "\nm_hPrinterFont ", (UINT)m_hPrinterFont);
if (m_hMirrorFont != NULL)
AFX_DUMP1(dc, "\nm_hMirrorFont ", (UINT)m_hMirrorFont);
AFX_DUMP1(dc, "\nm_aPageStart ", &m_aPageStart);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
static UINT NEAR PASCAL
ClipLine(CDC* pDC, int aCharWidths[256], int cxLine, int nTabStop,
LPCSTR lpszText, UINT nChars)
{
ASSERT_VALID(pDC);
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
// make an initial guess on the number of characters that will fit
int cx = 0;
LPCSTR lpszStart = lpszText;
LPCSTR lpszStop = lpszText + nChars;
LPCSTR lpsz = lpszStart;
while (lpsz < lpszStop)
{
if (*lpsz == '\t')
cx += nTabStop - (cx % nTabStop);
else
{
#ifdef AFXDATA_DEFINED
if (afxData.bDBCS && _AfxIsDBCSLeadByte(*lpsz))
{
++lpsz;
cx += tm.tmAveCharWidth;
}
else
#endif
cx += aCharWidths[(BYTE)*lpsz];
}
++lpsz;
if (cx > cxLine)
break;
}
// adjust for errors in the guess
cx = pDC->GetTabbedTextExtent(lpszStart, lpsz-lpszStart, 1, &nTabStop).cx;
if (cx > cxLine)
{
// remove characters until it fits
do
{
ASSERT(lpsz != lpszStart);
#ifdef AFXDATA_DEFINED
if (afxData.bDBCS)
lpsz = AnsiPrev(lpszStart, lpsz);
else
#endif
--lpsz;
cx = pDC->GetTabbedTextExtent(lpszStart, lpsz-lpszStart, 1, &nTabStop).cx;
} while (cx > cxLine);
}
else if (cx < cxLine)
{
// add characters until it doesn't fit
while (lpsz < lpszStop)
{
lpsz = AnsiNext(lpsz);
ASSERT(lpsz <= lpszStop);
cx = pDC->GetTabbedTextExtent(lpszStart, lpsz-lpszStart, 1, &nTabStop).cx;
if (cx > cxLine)
{
#ifdef AFXDATA_DEFINED
if (afxData.bDBCS)
lpsz = AnsiPrev(lpszStart, lpsz);
else
#endif
--lpsz;
break;
}
}
}
// return index of character just past the last that would fit
return lpsz - lpszText;
}
UINT // returns the line # which starts the next page
CMagmaEditView::PrintInsideRect(CDC* pDC, RECT& rectLayout,
UINT nLineStart, // this is the 0-based starting line
UINT nLineStop) // this is the 0-based ending line
// worker function for laying out text in a rectangle.
{
ASSERT_VALID(this);
ASSERT_VALID(pDC);
// get buffer and real starting and ending postions
UINT nLines = GetEditCtrl().GetLineCount();
if (nLineStart >= nLines)
return nLines;
LPSTR lpszText = new char[2048];
if (nLineStop > nLines)
nLineStop = nLines;
ASSERT(nLineStart < nLines);
// calculate text & tab metrics
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
int cyChar = tm.tmHeight;
int nTabStop = m_nTabStops*pDC->GetTabbedTextExtent("\t",1,0,NULL).cx / 8 / 4;
int aCharWidths[256];
pDC->GetCharWidth(0, 255, aCharWidths);
int y = rectLayout.top;
UINT cx = rectLayout.right - rectLayout.left;
VERIFY(pDC->SaveDC() != 0);
BOOL bLayoutOnly = pDC->IntersectClipRect(&rectLayout) == NULLREGION;
do
{
// Get the current line into lpszBuffer
GetEditCtrl().GetLine(nLineStart, lpszText, 2048);
UINT nChars = lstrlen(lpszText);
if (nChars == 0)
{
y += cyChar;
}
else
{
// non-word wrap printing (much easier and faster)
CRect rect(rectLayout.left, y, rectLayout.right, y+cyChar);
if (!bLayoutOnly && pDC->RectVisible(rect))
{
UINT nIndexClip = ClipLine(pDC, aCharWidths, cx, nTabStop,
lpszText, nChars);
if (nIndexClip < nChars)
{
#ifdef AFXDATA_DEFINED
if (_AfxIsDBCSLeadByte(*(lpszText+nIndexClip)))
nIndexClip++;
#endif
nIndexClip++;
}
pDC->TabbedTextOut(rect.left, y,
(LPCSTR)lpszText, nIndexClip, 1,
&nTabStop, rect.left);
}
y += cyChar;
}
nLineStart++;
}
while (nLineStart < nLineStop && y+cyChar <= rectLayout.bottom);
VERIFY(pDC->RestoreDC(-1));
ASSERT_VALID(this);
rectLayout.bottom = y;
return nLineStart;
}
/////////////////////////////////////////////////////////////////////////////
// CMagmaEditView Printing support
BOOL CMagmaEditView::OnPreparePrinting(CPrintInfo* pInfo)
{
return DoPreparePrinting(pInfo);
}
void CMagmaEditView::OnBeginPrinting(CDC* pDC, CPrintInfo*)
{
ASSERT_VALID(this);
ASSERT_VALID(pDC);
// initialize page start vector
ASSERT(m_aPageStart.GetSize() == 0);
m_aPageStart.Add(0);
ASSERT(m_aPageStart.GetSize() > 0);
if (m_hPrinterFont == NULL)
{
// get current screen font object metrics
CFont* pFont = GetFont();
LOGFONT lf;
if (pFont == NULL)
return;
pFont->GetObject(sizeof(LOGFONT), &lf);
static char BASED_CODE szSystem[] = "system";
if (lstrcmpi((LPCSTR)lf.lfFaceName, szSystem) == 0)
return;
// map to printer font metrics
HDC hDCFrom = ::GetDC(NULL);
lf.lfHeight = ::MulDiv(lf.lfHeight, pDC->GetDeviceCaps(LOGPIXELSY),
::GetDeviceCaps(hDCFrom, LOGPIXELSY));
lf.lfWidth = ::MulDiv(lf.lfWidth, pDC->GetDeviceCaps(LOGPIXELSX),
::GetDeviceCaps(hDCFrom, LOGPIXELSX));
::ReleaseDC(NULL, hDCFrom);
//
// MagmaEd uses an OEM_CHARSET screen font. However, for our
// HP LaserJet, Windows maps this font into a SCRIPT printer font.
// So, in order to get a normal font, we must set the lfCharSet to
// DEFAULT_CHARSET.
//
lf.lfCharSet = DEFAULT_CHARSET;
// create it, if it fails we just the the printer's default.
m_hMirrorFont = ::CreateFontIndirect(&lf);
m_hPrinterFont = m_hMirrorFont;
}
ASSERT_VALID(this);
}
BOOL CMagmaEditView::PaginateTo(CDC* pDC, CPrintInfo* pInfo)
// attempts pagination to pInfo->m_nCurPage, TRUE == success
{
ASSERT_VALID(this);
ASSERT_VALID(pDC);
CRect rectSave = pInfo->m_rectDraw;
UINT nPageSave = pInfo->m_nCurPage;
ASSERT(nPageSave > 1);
ASSERT(nPageSave >= (UINT)m_aPageStart.GetSize());
VERIFY(pDC->SaveDC() != 0);
pDC->IntersectClipRect(0, 0, 0, 0);
pInfo->m_nCurPage = m_aPageStart.GetSize();
while (pInfo->m_nCurPage < nPageSave)
{
ASSERT(pInfo->m_nCurPage == (UINT)m_aPageStart.GetSize());
OnPrepareDC(pDC, pInfo);
ASSERT(pInfo->m_bContinuePrinting);
pInfo->m_rectDraw.SetRect(0, 0,
pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
pDC->DPtoLP(&pInfo->m_rectDraw);
OnPrint(pDC, pInfo);
if (pInfo->m_nCurPage == (UINT)m_aPageStart.GetSize())
break;
++pInfo->m_nCurPage;
}
BOOL bResult = pInfo->m_nCurPage == nPageSave;
VERIFY(pDC->RestoreDC(-1));
pInfo->m_nCurPage = nPageSave;
pInfo->m_rectDraw = rectSave;
ASSERT_VALID(this);
return bResult;
}
void CMagmaEditView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
ASSERT_VALID(this);
ASSERT_VALID(pDC);
ASSERT(pInfo != NULL); // overriding OnPaint -- never get this.
if (pInfo->m_nCurPage > (UINT)m_aPageStart.GetSize() &&
!PaginateTo(pDC, pInfo))
{
// can't paginate to that page, thus cannot print it.
pInfo->m_bContinuePrinting = FALSE;
}
ASSERT_VALID(this);
}
void CMagmaEditView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
ASSERT_VALID(this);
ASSERT_VALID(pDC);
ASSERT(pInfo != NULL);
ASSERT(pInfo->m_bContinuePrinting);
CFont* pOldFont = NULL;
if (m_hPrinterFont != NULL)
pOldFont = pDC->SelectObject(CFont::FromHandle(m_hPrinterFont));
pDC->SetBkMode(TRANSPARENT);
UINT nPage = pInfo->m_nCurPage;
ASSERT(nPage <= (UINT)m_aPageStart.GetSize());
UINT nIndex = m_aPageStart[nPage-1];
// print as much as possible in the current page.
nIndex = PrintInsideRect(pDC, pInfo->m_rectDraw, nIndex, 0xFFFF);
if (pOldFont != NULL)
pDC->SelectObject(pOldFont);
// update pagination information for page just printed
if (nPage == (UINT)m_aPageStart.GetSize())
{
if (nIndex < (UINT) GetEditCtrl().GetLineCount())
m_aPageStart.Add(nIndex);
}
else
{
ASSERT(nPage+1 <= (UINT)m_aPageStart.GetSize());
ASSERT(nIndex == m_aPageStart[nPage+1-1]);
}
}
void CMagmaEditView::OnEndPrinting(CDC*, CPrintInfo*)
{
ASSERT_VALID(this);
m_aPageStart.RemoveAll();
if (m_hMirrorFont != NULL && m_hPrinterFont == m_hMirrorFont)
{
::DeleteObject(m_hMirrorFont);
m_hMirrorFont = NULL;
m_hPrinterFont = NULL;
}
}